﻿using System;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
using System.ComponentModel.Design;
using Microsoft.Win32;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell;
using EnvDTE;
using EnvDTE80;
using System.Windows.Forms;
using TLM.PlaylistGenerator;
using Microsoft.VisualStudio.TestTools.Vsip;
using System.Xml;
using System.Xml.Schema;
using System.IO;
using TLM.VsmdiReader;
using System.Text;
using Microsoft.VisualStudio.TestTools.TestTypes.Unit;

namespace TLM.VSExtension
{
    /// <summary>
    /// This is the class that implements the package exposed by this assembly.
    ///
    /// The minimum requirement for a class to be considered a valid package for Visual Studio
    /// is to implement the IVsPackage interface and register itself with the shell.
    /// This package uses the helper classes defined inside the Managed Package Framework (MPF)
    /// to do it: it derives from the Package class that provides the implementation of the 
    /// IVsPackage interface and uses the registration attributes defined in the framework to 
    /// register itself and its components with the shell.
    /// </summary>
    // This attribute tells the PkgDef creation utility (CreatePkgDef.exe) that this class is
    // a package.
    [PackageRegistration(UseManagedResourcesOnly = true)]
    // This attribute is used to register the information needed to show this package
    // in the Help/About dialog of Visual Studio.
    [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
    // This attribute is needed to let the shell know that this package exposes some menus.
    [ProvideMenuResource("Menus.ctmenu", 1)]
    [Guid(GuidList.guidTLMPkgString)]
    [ProvideAutoLoad("f1536ef8-92ec-443c-9ed7-fdadf150da82")]
    public sealed class TLMPackage : Package
    {
        const string VSMDI_EXTENSION = ".vsmdi";

        /// <summary>
        /// Default constructor of the package.
        /// Inside this method you can place any initialization code that does not require 
        /// any Visual Studio service because at this point the package object is created but 
        /// not sited yet inside Visual Studio environment. The place to do all the other 
        /// initialization is the Initialize method.
        /// </summary>
        public TLMPackage()
        {
            Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering constructor for: {0}", this.ToString()));
        }



        /////////////////////////////////////////////////////////////////////////////
        // Overridden Package Implementation
        #region Package Members

        /// <summary>
        /// Initialization of the package; this method is called right after the package is sited, so this is the place
        /// where you can put all the initialization code that rely on services provided by VisualStudio.
        /// </summary>
        protected override void Initialize()
        {
            Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString()));
            base.Initialize();

            // Add our command handlers for menu (commands must exist in the .vsct file)
            OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
            if (null != mcs)
            {
                // Create the command for the menu item.
                CommandID menuCommandID = new CommandID(GuidList.guidTLMCmdSet, (int)PkgCmdIDList.cmdidTLM);
                OleMenuCommand oleCommand = new OleMenuCommand(MenuItemCallback, menuCommandID);
                oleCommand.BeforeQueryStatus += new EventHandler(OnBeforeQueryStatus);
                mcs.AddCommand(oleCommand);
            }
        }

        /// <summary>
        /// Handles the click (and other events) on the item in the solution explorer
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="eventArgs">The <see cref="EventArgs"/> instance containing the event data.</param>
        internal void OnBeforeQueryStatus(object sender, EventArgs eventArgs)
        {
            OleMenuCommand oleCommand = sender as OleMenuCommand;
            if (oleCommand != null)
            {
                //DTE2 _applicationObject = this.GetService(typeof(DTE2)) as DTE2;
                DTE _applicationObject1 = this.GetService(typeof(DTE)) as DTE;
                if (_applicationObject1 != null)
                {
                    UIHierarchyItem solutionUiHierarchyItem;
                    UIHierarchy uiHierarchySolution = (UIHierarchy)_applicationObject1.Windows.Item(EnvDTE.Constants.vsWindowKindSolutionExplorer).Object;
                    //UIHierarchy uiHierarchySolution = _applicationObject.ToolWindows.SolutionExplorer;
                    solutionUiHierarchyItem = (UIHierarchyItem)((System.Array)uiHierarchySolution.SelectedItems).GetValue(0);
                    bool isTestList = string.Equals(Path.GetExtension(solutionUiHierarchyItem.Name), VSMDI_EXTENSION, StringComparison.OrdinalIgnoreCase);
                    oleCommand.Enabled = isTestList;
                }
                //UIHierarchy uiHierarchy = (UIHierarchy)ideObject.Windows.Item(EnvDTE.Constants.vsWindowKindSolutionExplorer).Object;
            }
        }


        #endregion

        /// <summary>
        /// This function is the callback used to execute a command when the a menu item is clicked.
        /// See the Initialize method to see how the menu item is associated to this function using
        /// the OleMenuCommandService service and the MenuCommand class.
        /// </summary>
        private void MenuItemCallback(object sender, EventArgs e)
        {
            // Show a Message Box to prove we were here
            DTE _applicationObject = this.GetService(typeof(DTE)) as DTE;
            if (_applicationObject != null)
            {
                UIHierarchyItem solutionUiHierarchyItem;
                UIHierarchy uiHierarchySolution = (UIHierarchy)_applicationObject.Windows.Item(EnvDTE.Constants.vsWindowKindSolutionExplorer).Object;
                solutionUiHierarchyItem = (UIHierarchyItem)((System.Array)uiHierarchySolution.SelectedItems).GetValue(0);
                string fileName = solutionUiHierarchyItem.Name;

                if (string.IsNullOrWhiteSpace(fileName))
                {
                    return;
                }

                // Build the solution. If the solution is already built, it won't do it again.
                _applicationObject.Solution.SolutionBuild.Build(true);

                // Check if the build succeeded (if LastBuildInfo is not 0 it couldn't build all projects successfully)
                if (_applicationObject.Solution.SolutionBuild.LastBuildInfo != 0)
                {
                    return;
                }

                string fullName = _applicationObject.Solution.FullName;
                string solutionPath = System.IO.Path.GetDirectoryName(fullName);                
                MigrateTestListToPlaylist(fileName, solutionPath);
            }
        }

        /// <summary>
        /// Retrieves teslist .vsmdi
        /// Parses the testlist to playlist
        /// Saves the playlist according to name and path chosen by user inside the FolderBrowserDialog
        /// </summary>
        /// <param name="fileName">name of the .vsmdi testlist file</param>
        /// <param name="solutionPath">path of the solution containing the testlist</param>
        private void MigrateTestListToPlaylist(string fileName, string solutionPath)
        {
            try
            {
                TLM.Wizard.Context.InitObject.PathToVsmdi = Path.Combine(solutionPath, fileName);
                TLM.Wizard.Context.InitObject.TMI = GetService(typeof(STestManagement)) as ITestManagement;
                TLM.Wizard.Context.InitObject.UnitTestService = GetService(typeof(SUnitTestService)) as ITuip;

                TLM.Wizard.WizardBase wiz = new Wizard.WizardBase();            
                wiz.ShowModal();
            }
            catch (XmlException ex)
            {
                MessageBox.Show(String.Format(CultureInfo.InvariantCulture,"There is a error occurred while handling the vsmdi file '{0}'\nDetails: {1}", fileName, ex.Message),
                                "Error handling the vsmdi file", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (XmlSchemaValidationException ex)
            {
                MessageBox.Show(String.Format(CultureInfo.InvariantCulture, "The vsmdi file '{0}'is not XSD-valid\nDetails: {1}", fileName, ex.Message),
                                "Invalid vsmdi file", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (Exception ex)
            {

                MessageBox.Show(String.Format(CultureInfo.InvariantCulture, "There is a unknown error occurred\nDetails: {0}", ex.Message),
                                "Unknown error occurred", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}
